/*
 * RevenueSourceDAO.java
 *
 * Created on March 27, 2007, 9:31 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package edu.byu.isys413.samlam;

import java.sql.*;
import java.util.LinkedList;
import java.util.List;

/**
 *
 * @author Sam
 */
public abstract class RevenueSourceDAO{
    ///////////////////////////////////////
    ///   Singleton pattern
    
    private static RevenueSourceDAO instance;
    
    /** Creates a new instance of RevenueSourceDAO */
    protected RevenueSourceDAO() {
    }
    
    /////////////////////////////////
    ///   CREATE
    
    /**
     * Create is an abstract method because it needs to be implemented differently for each
     * RevenueSource
     */
    public abstract RevenueSource create() ;
    
    
    /////////////////////////////////////
    ///   READ
    
    /**
     * This is the public read statement.  It loads an existing record
     * from the database.
     */
    public abstract RevenueSource read(String id) throws DataException;
    
    /**
     *  This is a package method that is called by the public read (above) or
     *  by another DAO.  Either way we already have a connection to the database
     *  to use.  The user (controller) code never calls this one directly, since
     *  it can't know about Connection objects or SQLExceptions.
     */
    synchronized RevenueSource read(String id, Connection conn) throws SQLException, DataException {
        // check again if the id is in the cache, and if so,
        // just get it from the cache.  we need to check again
        // because this method might be called directly from
        // another DAO rather than from read above.
        RevenueSource revsource = (RevenueSource)Cache.getInstance().get(id);
        if(revsource == null){
            throw new DataException("Object was not in Cache");
        }
        // if not in the cache, get a result set from
        // a SELECT * FROM table WHERE id=guid
        Statement stmt = conn.createStatement();
        ResultSet rs = stmt.executeQuery("SELECT * FROM revsource WHERE revenuesourceid = '"+ id + "'");
        //create a prepared statement
        //query the database
        //call sets from the result set
        String memberId=null;
        if (rs.next()) {
            revsource.setPrice(rs.getDouble("price"));
            revsource.setType(rs.getString("type"));
            revsource.setTransactionLineId("transactionlineid");
            revsource.setDescription(rs.getString("description"));
            
            // save to the cache
            
            Cache.getInstance().touch(revsource.getId());
            stmt.close();
        }else{
            throw new DataException("Object was not found in the database.");
            
        }
        
        return revsource;
    }
    
    //////////////////////////////////
    ///   UPDATE
    
    /**
     * This is the public save method.  It is what is called when
     * the user (controller) code wants to save or update an object
     * into the database.
     */
    public abstract void save(RevenueSource revsource) throws DataException ;
    
    
    /**
     *  This is a package method that is called by the public save (above) or
     *  by another DAO.  Either way we already have a connection to the database
     *  to use.  The user (controller) code never calls this one directly, since
     *  it can't know about Connection objects or SQLExceptions.
     *
     *  By having other DAOs call this save method (rather than update or
     *  insert below, each DAO in a chained save (like the RevenueSourceDAO calling
     *  MembershipDAO calling InterestDAO save chain) can independently decide
     *  whether to udpate or insert the BO it's saving.  That's why I made
     *  update and insert private rather than package level -- if you call
     *  them directly from another DAO, this DAO can't decide whether it's
     *  object needs to be inserted or updated.
     */
    synchronized void save(RevenueSource revsource, Connection conn) throws SQLException, DataException {
        // check the dirty flag in the object.  if it is dirty,
        // run update or insert
        if (revsource.isDirty()) {
            
            if (revsource.isObjectAlreadyInDB() == true) {
                update(revsource, conn);
            }else{
                insert(revsource, conn);
            }
            // set the dirty flag to false now that we've saved it
            
        }
        // touch the cache for the object
        Cache.getInstance().touch(revsource.getId());
    }
    
    /**
     * This method is really a part of save(bo, conn) above.  It could be
     * embedded directly in it, but I've separated it into it's own method
     * to isolate the SQL udpate statement and make it more readable.  But
     * logically, it's really just a part of save.
     */
    private synchronized void update(RevenueSource revsource, Connection conn) throws SQLException, DataException {
        // do the update statement
        Statement stmt = conn.createStatement();
        stmt.executeUpdate("UPDATE revenuesource set revenuesourceid='"+revsource.getId()+"', type='"+revsource.getType()+"', description='"+revsource.getDescription()+"', price=" + revsource.getPrice() + ", transactionlineid='"+revsource.getTransactionLineId()+"'");
        stmt.close();
    }
    
    /**
     * This method is really a part of save(bo, conn) above.  It could be
     * embedded directly in it, but I've separated it into it's own method
     * to isolate the SQL insert statement and make it more readable.  But
     * logically, it's really just a part of save.
     */
    private synchronized void insert(RevenueSource revsource, Connection conn) throws SQLException, DataException {
        // do the insert SQL statement
        Statement stmt = conn.createStatement();
        stmt.executeUpdate("INSERT INTO revenuesource VALUES ('"+revsource.getId()+"', '"+revsource.getType()+"', '"+revsource.getDescription()+"',"+revsource.getPrice()+", '"+revsource.getTransactionLineId()+"')");
        stmt.close();
        // tell the object that it's now in the db (so we call update next time not insert)
        revsource.setObjectAlreadyInDB(true);
    }
    
    
    ////////////////////////////////////
    ///   DELETE
    // we are not supporting because we never want to delete the revsource from
    // our database.
}
